#ifndef JOUEUR_H
#define JOUEUR_H 1

#include "ADDObjetBase.h"

//#include "Classe.h"

//#include "debugstreams.h"

#include "StatusCode.h"

#include "CapaciteRaciale.h"

#include "NonMartiale.h"

#include "Sort.h"

#include <vector>
#include <map>

using namespace std;

/**
 * @addtogroup Utilitaires
 * @{
 */

/**
 * Sert à énumérer les différents types de classes multiples.
 */
enum TypeMulti  {
  Non, /**< Le Joueur n'a qu'une classe */
  Mul, /**< Le Joueur est multiclassé */
  Jum /**< Le Joueur a jumelé */
};

/**
 * Enumère les Dons / Désavantages
 */
enum TypeComp  {Don, Desav};

/**
 * \}
 */

class Race;
class Classe;
class Parser;
class ElementDOM;
class LireMartiales;

/**
 * Cette classe permet la création de la feuille de perso. Un Joueur
 * possède une Race, une (ou plusieurs) Classe. Depuis Joueur il est
 * possible décire un fichier XML, d'en lire et finalement de produire
 * le code LaTeX qui fera une jolie feuille de personnage. Le Joueur
 * est en fait l'implémentation du PJ.
 *
 * @todo Pourquoi ne pas mettre les traits dans Joueur plutôt que dans
 * Race ? Le problème serait que beaucoup de méthodes de Classe on
 * besoin des traits pour fonctionner, mais ce n'est pas optimal pour
 * les multiclassés...
 *
 * @todo trouver un moyen de changer l'affichage des compétences
 * martiales pour 1) arme de prédilection, expertise martiale et les
 * différents niveaux de spécialisations.
 *
 * @todo Rendre la "progression" plus simple : au lieu de tout coder
 * dans une méthode (e tde recopier le code dans le GUI, mettre des
 * accesseurs, etc...
 *
 * @todo Remplacer ListNonMart par NonMartiale.
 *
 * @author Johan "Solo" Luisier
 */
class Joueur : public ADDObjetBase
{
 public:
  Joueur();
  Joueur(Classe* classe, Race* race, const string& nom);
  Joueur( map< string, string >* infoXML );
  Joueur( Parser const* parser );
  ~Joueur();
  /****************************************************************************
   *
   * Méthodes
   *
   ***************************************************************************/
  void information( ostream& os );
  void information( FlotMessage& flot );
  string demanderNom() const;
  void ecrireXml() const;
  void setPP(const unsigned& pps, const bool& creation = false);
  void setPV(const unsigned& pv);
  void setTraits( const vector< unsigned >& traits );
  void setDons(const vector<unsigned>& vec);
  void setDesavantages(const vector<unsigned>& vec);
  void setDiverses(const vector<unsigned>& vec);
  void setMartiales(const vector<unsigned>& vec);
  void setAcces(const vector<unsigned>& vec);
  void ajouterDiverses(const vector<unsigned>& aAjouter);
  void ajouterMartiales(const vector<unsigned>& aAjouter);
  void initDiverses(const vector<unsigned>& vec);

  void ajoutClasse(Classe* classe);
  void ecrireTex(const bool& UI = false) const;
  unsigned nbrDons() const;
  unsigned nbrDesavantages() const;
  unsigned nbrCompetences() const;
  unsigned nbrCompMartiales() const;
  string nom() const;
  string race() const;
  const unsigned& trait( const unsigned& i ) const;
  const vector< unsigned >* traits() const;
  const Race* racePtr() const;
  unsigned nbrClasses() const;
  Classe* classePtr(const unsigned& i = 99) const;
  void traits(unsigned tab[7]) const;
  string capaRaciale() const;
  unsigned typeMulti() const;
  unsigned nbrPV() const;
  unsigned nbrPP() const;
  string ajustementPV() const;
  const vector<TypeClasse>* acces(unsigned& nbr) const;
  const vector<Sort>* sorts(unsigned& nbr, const unsigned& i = 0) const;
  const vector<unsigned>* dons(unsigned& nbr) const;
  const vector<unsigned>* desavantages(unsigned& nbr) const;
  const vector<unsigned>* diverses(unsigned& nbr) const;
  const vector<unsigned>* martiales(unsigned& nbr) const;
  unsigned listeDons(vector<CapaciteRaciale> &vec) const;
  unsigned listeDesavantages(vector<CapaciteRaciale> &vec) const;
  const string* listeCategories(unsigned& nbr) const;
  const vector< NonMartiale >* listeCompetences(unsigned& nbr) const;
  const NonMartiale & compDsListe(const unsigned& i) const;
  const vector<unsigned>* martialeClasse(const string& nomClasse)
    const;
  const unsigned& niveauMagie() const;
  static void setLevel(const unsigned& level, const unsigned& n);
  string aSortsMage(vector<Classe *>& vec) const;
  unsigned aSpecialisation() const;
  string convertNom() const;
  unsigned prixArmePredilection() const;
  unsigned prixExpertiseMartiale() const;
  unsigned prixSpecialisation() const;

  /****************************************************************************
   *
   * Fonctions de gestion de l'évolution du Joueur
   *
   ***************************************************************************/

  void determinerDonsDesavantages(const TypeComp& quoi);
  void determinerCompetences();
  void augmenterCompetences();
  void determinerCompMartiales();
  void augmenterCompMartiales();
  StatusCode ajouterXP(const unsigned& xp);
  void ajouterPP(const unsigned& pp);
  void ajouterPV(const unsigned& pv);

 protected:
  /**
   * Nom du personnage
   */
  string Nom;
  /**
   * Traits du personnage (pour le moment en 'beta').
   */
  vector< unsigned > Traits;
  /**
   * Contient la (les) classe(s) du personnage
   * @see Classe
   */
  vector< Classe* > J_classe;
  /**
   * Contient la race du personnage
   * @see Race
   */
  Race* J_race;
  unsigned TAc0, /**< TAC0 du personnage */
    PV,          /**< Nombre de pts de vie */
    PP,          /**< Nombre de pp restant */
    nb_classes;  /**< Nombre de classes (dimension de J_classe) */
  /**
   * Classe d'armure
   */
  int CA;
  vector<unsigned> J_CompDiv, /**< Compétences diverses */
    J_Dons,                   /**< Dons */
    J_Desavantages,           /**< Désavantages */
    J_Martiales;              /**< Compétences martiales */
  /**
   * Compétences diverses accessibles (Roublard, Combattant, etc...)
   */
  vector<TypeClasse> J_CompAccess;

  /**
   * 
   */
  LireMartiales * LireArmesXML;
 
  /****************************************************************************
   *
   * Niveaux de sortie des sous-fonctions
   * 'static', toujours par soucis d'optimisation
   *
   ***************************************************************************/

  /**
   * Niveau de sortie basique pour la gestion du XML.
   */
  static DebugLevelType fonction_elementaire_xml;
  /**
   * Niveau de sortie pour les fonctions de récupération d'information
   * à partir du XML.
   */
  static DebugLevelType fonction_recuperation_xml;
  /**
   * Niveau de sortie des fonctions écrivant les sources .tex.
   */
  static DebugLevelType fonction_tex;
  /**
   * Niveau de sortie pour les autres fonctions.
   */
  static DebugLevelType interne;

  /**
   * Permet de déterminer si les niveaux de sorties ont bien été
   * initialisés.
   */
  static bool niveauxLus;
  /**
   * Liste des noms des niveaux de sorties paramétrables.
   */
  static const vector< string > NomsNiveaux;

  /**
   * Permet de déterminer si la liste des armes a été récupérée par
   * LireArmes.
   */
  static bool armesLues;

 private:
  /****************************************************************************
   *
   * Ajustements dus aux traits, sont stockés sous forme de tableaux 'static'
   * par soucis d'optimisation.
   *
   ***************************************************************************/

  /**
   * Ajustements au toucher, aux dégâts, charge autorisée, charge
   * maximale, défoncer portes, barreaux & herses.
   */
  static const string Aj_Force[30][6];
  /**
   * Ajustement réflexe, ajustement aux missiles, ajustement défensif.
   */
  static const string Aj_Dexterite[14][3];
  /**
   * Ajustement au PV, choc métabolique, régénération, survie à la
   * résurection, ajustement aux JS contre les Poisons.
   */
  static const string Aj_Const[25][5];
  /**
   * Nombre de langues, niveau de sort maximal, pourcentage
   * d'apprentissage de sorts, nombre maximal de sort par niveau,
   * immunité aux illusions.
   */
  static const string Aj_Int[19][5];
  /**
   * Bonus aux JS contre les sorts mentaux, sorts bonus, pourcentage
   * d'échec des sorts, immunité aux sorts.
   */
  static const string Aj_Sagesse[24][4];
  /**
   * Nombre de compagnon d'arme, loyauté inspirée, bonus à la
   * réaction.
   */
  static const string Aj_Charisme[24][3];

  /****************************************************************************
   *
   * Dons, désavantages et compétences non-martiales
   * 'static', toujours par soucis d'optimisation
   *
   ***************************************************************************/

  static const vector< CapaciteRaciale > Dons, /**< Liste des dons @see
					   CapaciteRaciale */
    Desavantages;                       /**< Liste des désavantages
					   @see CapaciteRaciale */

  /**
   * Liste des compétences diverses.
   * @see NonMartiale
   */
  static const vector< NonMartiale > CompetencesDiverses;

  /**
   * Liste des catégories de compétences diverses (Générale,
   * Combattant, ...).
   */
  static const string CategoriesCompetences[5];

  /**
   * Liste des compétences martiales disponibles pour chaque classe
   * 'static', toujours par soucis d'optimisation.\n
   *
   * Pour chaque classe on garde la position dans
   * CompMartialesParClasse de sa liste d'armes.
   */
  static const map<string, unsigned> GererClasses;

  /**
   * Ce tableau contient des pointeurs vers les listes d'armes
   * disponibles pour chaque type de classe.\n
   *
   * Les combattants ont accès à toutes les armes, alors on ne déclare
   * pas de variables pour eux, et CompMartialesParClasse contient 0
   * pour ces classes.\n
   *
   * On utilise une astuce, si deux classes ont la même liste d'arme,
   * il n'existe qu'une seule liste, mais on va ici stocker deux
   * poitneurs différents.
   */
  static const vector<unsigned>* CompMartialesParClasse[5];

  /*
   * Mages et Spécialistes on la même sélection d'armes => un seul
   * tableau mais deux pointeurs dans CompMartialesParClasse.
   */
  static const vector<unsigned>
    CompMarMage, /**< Liste des armes accessbibes aux Mages et Spécialistes */
    CompMarClerc, /**< Liste d'armes accessibles aux Prêtres */
    CompMarDruide, /**< Liste d'armes accessibles aux Druides */
    CompMarVoleur;/**< Liste d'armes accessibles aux Voleurs */

  /**
   * Gestion de la mémoire allouée dynamiquement.
   */
  bool libere_mem;
  /**
   * Gestion de multiclassé ou classes jumelées (=> gestion des XPs).
   * @see TypeMulti
   */
  TypeMulti TM_switch;
  void modificateurPP();
  void modificateurVal(unsigned& val, const unsigned& trait) const;
  void nettoieTC();
  void gererDiverses(const vector<unsigned>& numeros,
		      vector<unsigned>& comp) const;
  void gererMartiales(const vector< unsigned >& numeros,
		      vector< unsigned >& comp) const;

  /****************************************************************************
   *
   * Sous-fonctions qui écrivent les différentes parties du code .tex
   * nécessaire pour la feuille complète.
   *
   ***************************************************************************/

  void ecrireTraitsTex() const;
  void ecrireJSTex() const;
  void ecrireScoresTex() const;
  void ecrireRaceTex() const;
  void ecrireClasseTex() const;
  void ecrireCompTex() const;
  void ecrireSortsTex() const;

  void construitJoueur( map< string, string >* infoXML );

  StatusCode verifieBalise(const ElementDOM* elDom, const string& bal) const;
  void faireVerificationBalise(const ElementDOM* elDom, const string& bal) const;
  void lireClasse(const ElementDOM* elDom, const string& prefixe,
		  const Parser* parser, map< string, string >& infos) const;
  /*
    void lireEtStockerDonnees(const ElementDOM* elDom, const string& bal
    map< string, string >& infos) const;
  */
};

#endif
